package com.gmadmin.common;

import org.springframework.lang.Nullable;

/**
 * 通用状态码
 *
 * @author zhangliang
 * @version 1.0
 * @date 2021/1/25 11:54
 */
public enum HttpStatus implements IStatus {
    CONTINUE(100, HttpStatus.Series.INFORMATIONAL, "继续..."),
    SWITCHING_PROTOCOLS(101, HttpStatus.Series.INFORMATIONAL, "切换协议"),
    PROCESSING(102, HttpStatus.Series.INFORMATIONAL, "Processing"),
    CHECKPOINT(103, HttpStatus.Series.INFORMATIONAL, "Checkpoint"),
    OK(200, HttpStatus.Series.SUCCESSFUL, "请求成功"),
    CREATED(201, HttpStatus.Series.SUCCESSFUL, "成功请求并创建了新的资源"),
    ACCEPTED(202, HttpStatus.Series.SUCCESSFUL, "已经接受请求，但未处理完成"),
    NON_AUTHORITATIVE_INFORMATION(203, HttpStatus.Series.SUCCESSFUL, "非授权信息"),
    NO_CONTENT(204, HttpStatus.Series.SUCCESSFUL, "服务器成功处理，但未返回内容"),
    RESET_CONTENT(205, HttpStatus.Series.SUCCESSFUL, "服务器处理成功，用户终端（例如：浏览器）应重置文档视图"),
    PARTIAL_CONTENT(206, HttpStatus.Series.SUCCESSFUL, "服务器成功处理了部分GET请求"),
    MULTI_STATUS(207, HttpStatus.Series.SUCCESSFUL, "Multi-Status"),
    ALREADY_REPORTED(208, HttpStatus.Series.SUCCESSFUL, "Already Reported"),
    IM_USED(226, HttpStatus.Series.SUCCESSFUL, "IM Used"),
    MULTIPLE_CHOICES(300, HttpStatus.Series.REDIRECTION, "Multiple Choices"),
    MOVED_PERMANENTLY(301, HttpStatus.Series.REDIRECTION, "Moved Permanently"),
    FOUND(302, HttpStatus.Series.REDIRECTION, "Found"),
    /** @deprecated */
    @Deprecated
    MOVED_TEMPORARILY(302, HttpStatus.Series.REDIRECTION, "Moved Temporarily"),
    SEE_OTHER(303, HttpStatus.Series.REDIRECTION, "See Other"),
    NOT_MODIFIED(304, HttpStatus.Series.REDIRECTION, "Not Modified"),
    /** @deprecated */
    @Deprecated
    USE_PROXY(305, HttpStatus.Series.REDIRECTION, "Use Proxy"),
    TEMPORARY_REDIRECT(307, HttpStatus.Series.REDIRECTION, "Temporary Redirect"),
    PERMANENT_REDIRECT(308, HttpStatus.Series.REDIRECTION, "Permanent Redirect"),
    BAD_REQUEST(400, HttpStatus.Series.CLIENT_ERROR, "客户端请求的语法错误，服务器无法理解"),
    /**
     * 当前请求需要验证或者验证已过期或者此用户角色没有访问次api的权限
     */
    UNAUTHORIZED(401, HttpStatus.Series.CLIENT_ERROR, "当前请求需要用户验证或者验证已过期"),
    PAYMENT_REQUIRED(402, HttpStatus.Series.CLIENT_ERROR, "Payment Required"),
    FORBIDDEN(403, HttpStatus.Series.CLIENT_ERROR, "api请求失败"),
    NOT_FOUND(404, HttpStatus.Series.CLIENT_ERROR, "请求失败，请求所希望得到的资源未被在服务器上发现"),
    METHOD_NOT_ALLOWED(405, HttpStatus.Series.CLIENT_ERROR, "请求行中指定的请求方法不能被用于请求相应的资源"),
    NOT_ACCEPTABLE(406, HttpStatus.Series.CLIENT_ERROR, "请求的资源的内容特性无法满足请求头中的条件，因而无法生成响应实体"),
    PROXY_AUTHENTICATION_REQUIRED(407, HttpStatus.Series.CLIENT_ERROR, "Proxy Authentication Required"),
    REQUEST_TIMEOUT(408, HttpStatus.Series.CLIENT_ERROR, "请求超时"),
    CONFLICT(409, HttpStatus.Series.CLIENT_ERROR, "由于和被请求的资源的当前状态之间存在冲突，请求无法完成"),
    GONE(410, HttpStatus.Series.CLIENT_ERROR, "被请求的资源在服务器上已经不再可用，而且没有任何已知的转发地址"),
    LENGTH_REQUIRED(411, HttpStatus.Series.CLIENT_ERROR, "服务器拒绝在没有定义 Content-Length 头的情况下接受请求"),
    PRECONDITION_FAILED(412, HttpStatus.Series.CLIENT_ERROR, "服务器在验证在请求的头字段中给出先决条件时，没能满足其中的一个或多个"),
    PAYLOAD_TOO_LARGE(413, HttpStatus.Series.CLIENT_ERROR, "服务器拒绝处理当前请求，因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围"),
    /** @deprecated */
    @Deprecated
    REQUEST_ENTITY_TOO_LARGE(413, HttpStatus.Series.CLIENT_ERROR, "服务器拒绝处理当前请求，因为该请求提交的实体数据大小超过了服务器愿意或者能够处理的范围"),
    URI_TOO_LONG(414, HttpStatus.Series.CLIENT_ERROR, "请求的URI 长度超过了服务器能够解释的长度，因此服务器拒绝对该请求提供服务"),
    /** @deprecated */
    @Deprecated
    REQUEST_URI_TOO_LONG(414, HttpStatus.Series.CLIENT_ERROR, "请求的URI 长度超过了服务器能够解释的长度，因此服务器拒绝对该请求提供服务"),
    UNSUPPORTED_MEDIA_TYPE(415, HttpStatus.Series.CLIENT_ERROR, "服务器无法处理请求附带的媒体格式"),
    REQUESTED_RANGE_NOT_SATISFIABLE(416, HttpStatus.Series.CLIENT_ERROR, "客户端请求的范围无效"),
    EXPECTATION_FAILED(417, HttpStatus.Series.CLIENT_ERROR, "Expectation Failed"),
    I_AM_A_TEAPOT(418, HttpStatus.Series.CLIENT_ERROR, "I'm a teapot"),
    /** @deprecated */
    @Deprecated
    INSUFFICIENT_SPACE_ON_RESOURCE(419, HttpStatus.Series.CLIENT_ERROR, "Insufficient Space On Resource"),
    /** @deprecated */
    @Deprecated
    METHOD_FAILURE(420, HttpStatus.Series.CLIENT_ERROR, "Method Failure"),
    /** @deprecated */
    @Deprecated
    DESTINATION_LOCKED(421, HttpStatus.Series.CLIENT_ERROR, "Destination Locked"),
    UNPROCESSABLE_ENTITY(422, HttpStatus.Series.CLIENT_ERROR, "请求格式正确，但是由于含有语义错误，无法响应"),
    LOCKED(423, HttpStatus.Series.CLIENT_ERROR, "当前资源被锁定"),
    FAILED_DEPENDENCY(424, HttpStatus.Series.CLIENT_ERROR, "由于之前的某个请求发生的错误，导致当前请求失败"),
    TOO_EARLY(425, HttpStatus.Series.CLIENT_ERROR, "Too Early"),
    UPGRADE_REQUIRED(426, HttpStatus.Series.CLIENT_ERROR, "需要升级"),
    PRECONDITION_REQUIRED(428, HttpStatus.Series.CLIENT_ERROR, "要求先决条件"),
    TOO_MANY_REQUESTS(429, HttpStatus.Series.CLIENT_ERROR, "请求太多"),
    REQUEST_HEADER_FIELDS_TOO_LARGE(431, HttpStatus.Series.CLIENT_ERROR, "请求头字段太大"),
    UNAVAILABLE_FOR_LEGAL_REASONS(451, HttpStatus.Series.CLIENT_ERROR, "该请求因法律原因不可用"),
    INTERNAL_SERVER_ERROR(500, HttpStatus.Series.SERVER_ERROR, "服务器内部错误，无法完成请求"),
    NOT_IMPLEMENTED(501, HttpStatus.Series.SERVER_ERROR, "服务器不支持请求的功能，无法完成请求"),
    BAD_GATEWAY(502, HttpStatus.Series.SERVER_ERROR, "作为网关或者代理工作的服务器尝试执行请求时，从远程服务器接收到了一个无效的响应"),
    SERVICE_UNAVAILABLE(503, HttpStatus.Series.SERVER_ERROR, "由于超载或系统维护，服务器暂时的无法处理客户端的请求。延时的长度可包含在服务器的Retry-After头信息中"),
    GATEWAY_TIMEOUT(504, HttpStatus.Series.SERVER_ERROR, "充当网关或代理的服务器，未及时从远端服务器获取请求"),
    HTTP_VERSION_NOT_SUPPORTED(505, HttpStatus.Series.SERVER_ERROR, "服务器不支持请求的HTTP协议的版本，无法完成处理"),
    VARIANT_ALSO_NEGOTIATES(506, HttpStatus.Series.SERVER_ERROR, "Variant Also Negotiates"),
    INSUFFICIENT_STORAGE(507, HttpStatus.Series.SERVER_ERROR, "储存不足"),
    LOOP_DETECTED(508, HttpStatus.Series.SERVER_ERROR, "Loop Detected"),
    BANDWIDTH_LIMIT_EXCEEDED(509, HttpStatus.Series.SERVER_ERROR, "超出带宽限制"),
    NOT_EXTENDED(510, HttpStatus.Series.SERVER_ERROR, "未扩展"),
    NETWORK_AUTHENTICATION_REQUIRED(511, HttpStatus.Series.SERVER_ERROR, "需要网络身份验证"),

    USER_ROLES_NOT_FOUND(10001, HttpStatus.Series.CLIENT_ERROR , "未发现用户角色"),
    USER_NOT_FOUND(10001,HttpStatus.Series.CLIENT_ERROR , "用户不存在"),
    HTTP_NOT_METHOD(10002,HttpStatus.Series.CLIENT_ERROR , "请求方法不存在"),
    LOGIN_NOT_FOUND(10003,HttpStatus.Series.CLIENT_ERROR , "找不到当前登录的信息"),
    TOKEN_PARSE_ERROR(10004, Series.CLIENT_ERROR ,"token解析错误" ),
    CODE_HAS_ERROR(10005, Series.CLIENT_ERROR ,"验证码错误" ),
    CODE_HAS_EXPIRED(10005, Series.CLIENT_ERROR ,"验证码已过期" ),
    API_NOT_FOUND(10006, Series.CLIENT_ERROR ,"api请求地址不存在" ),
    LOGIN_HAS_EXPIRATION(401, Series.CLIENT_ERROR ,"当前登录状态已过期" ),
    REDIS_TIME_OUT(5001, Series.SERVER_ERROR,"redis连接超时" ),
    USER_STATUE_LOCKED(10007, Series.CLIENT_ERROR ,"当前用户已被锁定" ),
    USER_STATUE_EXPIRED(10007, Series.CLIENT_ERROR ,"当前用户密码已过期，请修改密码登录" ),
    USER_STATUE_DISABLE(10007, Series.CLIENT_ERROR ,"当前用户已被禁用,无法正常使用" ),
    USER_STATUE_CANCELLATION(10007, Series.CLIENT_ERROR ,"当前用户已被注销,无法正常使用"),;


    private static final HttpStatus[] VALUES = values();

    /**
     * 异常代码
     */
    private final int value;
    /**
     * 所属系列
     */
    private final HttpStatus.Series series;
    /**
     * 异常原因
     */
    private final String reasonPhrase;

    HttpStatus(int value, HttpStatus.Series series, String reasonPhrase) {
        this.value = value;
        this.series = series;
        this.reasonPhrase = reasonPhrase;
    }

    @Override
    public Integer value() {
        return this.value;
    }

    public HttpStatus.Series series() {
        return this.series;
    }

    @Override
    public String getReasonPhrase() {
        return this.reasonPhrase;
    }

    public boolean is1xxInformational() {
        return this.series() == HttpStatus.Series.INFORMATIONAL;
    }

    public boolean is2xxSuccessful() {
        return this.series() == HttpStatus.Series.SUCCESSFUL;
    }

    public boolean is3xxRedirection() {
        return this.series() == HttpStatus.Series.REDIRECTION;
    }

    public boolean is4xxClientError() {
        return this.series() == HttpStatus.Series.CLIENT_ERROR;
    }

    public boolean is5xxServerError() {
        return this.series() == HttpStatus.Series.SERVER_ERROR;
    }

    public boolean isError() {
        return this.is4xxClientError() || this.is5xxServerError();
    }

    @Override
    public String toString() {
        return this.value + " " + this.name();
    }

    public static HttpStatus valueOf(int statusCode) {
        HttpStatus status = resolve(statusCode);
        if (status == null) {
            throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
        } else {
            return status;
        }
    }

    @Nullable
    public static HttpStatus resolve(int statusCode) {
        HttpStatus[] var1 = VALUES;
        int var2 = var1.length;

        for(int var3 = 0; var3 < var2; ++var3) {
            HttpStatus status = var1[var3];
            if (status.value == statusCode) {
                return status;
            }
        }

        return null;
    }



    public  enum Series {
//        信息服务器收到请求，需要请求者继续执行操作
        INFORMATIONAL(1),
//        成功，操作被成功接收并处理
        SUCCESSFUL(2),
//        重定向，需要进一步的操作以完成请求
        REDIRECTION(3),
//        客户端错误，请求包含语法错误或无法完成请求
        CLIENT_ERROR(4),
//       服务器错误，服务器在处理请求的过程中发生了错误
        SERVER_ERROR(5);

        private final int value;

        private Series(int value) {
            this.value = value;
        }

        public int value() {
            return this.value;
        }

        public static HttpStatus.Series valueOf(HttpStatus status) {
            return status.series;
        }

        public static HttpStatus.Series valueOf(int statusCode) {
            HttpStatus.Series series = resolve(statusCode);
            if (series == null) {
                throw new IllegalArgumentException("No matching constant for [" + statusCode + "]");
            } else {
                return series;
            }
        }

        @Nullable
        public static HttpStatus.Series resolve(int statusCode) {
            int seriesCode = statusCode / 100;
            HttpStatus.Series[] var2 = values();
            int var3 = var2.length;

            for(int var4 = 0; var4 < var3; ++var4) {
                HttpStatus.Series series = var2[var4];
                if (series.value == seriesCode) {
                    return series;
                }
            }

            return null;
        }
    }
}
